const express = require('express');
const ffmpeg = require('fluent-ffmpeg');
const axios = require('axios');
const { v4: uuidv4 } = require('uuid');
const path = require('path');
const fs = require('fs');
require('dotenv').config();

// 文件存储配置
const UPLOAD_DIR = path.join(__dirname, 'uploads');
const FRAME_INTERVAL = 30; // 默认30秒取一帧

const app = express();
app.use(express.json());
app.use(express.static(__dirname));
app.use('/frames', express.static(UPLOAD_DIR));

// 创建上传目录


app.post('/api/extract-frames', async (req, res) => {
  try {
    const videoUrl = req.body.url;
    const precision = parseInt(req.body.precision) ?? 2;
    if(precision<0) precision=0
    if(precision>10) precision=10
    console.log("请求开始：",req.body.url,req.body.precision)
    // 下载视频到临时文件
    const tempVideoPath = await downloadVideo(videoUrl);
    // 获取视频时长
    const duration = await getVideoDuration(tempVideoPath);
    // 计算需要提取的帧数
    const frameCount = precision === 10 ? Math.ceil(duration) : Math.ceil(duration / (30 / (precision + 1)));
    // 生成唯一任务ID
    const taskId = uuidv4();
    const outputDir = path.join(UPLOAD_DIR, taskId);
    // 提取关键帧
    await extractKeyFrames(tempVideoPath, outputDir, frameCount);
    // 读取关键帧图片文件名
    const frameFiles = await fs.promises.readdir(outputDir);
    const frameUrls = frameFiles.map(file => `${process.env.BASE_URL}/frames/${taskId}/${file}`);
    res.json({
      status: 'complated',
      taskId: taskId,
      frameCount: frameCount,
      frameUrls: frameUrls
    });
    // 删除临时视频文件
    fs.unlinkSync(tempVideoPath);
  } catch (error) {
    console.error('处理失败:', error);
    res.status(500).json({ error: error.message });
  }
});

async function downloadVideo(url) {
  const response = await axios({
    url,
    method: 'GET',
    responseType: 'stream'
  });

  const tempPath = path.join(UPLOAD_DIR, `temp_${Date.now()}.mp4`);
  const writer = fs.createWriteStream(tempPath);
  
  response.data.pipe(writer);

  return new Promise((resolve, reject) => {
    writer.on('finish', () => resolve(tempPath));
    writer.on('error', reject);
  });
}

async function getVideoDuration(filePath) {
  return new Promise((resolve, reject) => {
    ffmpeg.ffprobe(filePath, (err, metadata) => {
      if (err) reject('无法解析视频文件');
      resolve(metadata.format.duration);
    });
  });
}

async function extractKeyFrames(videoPath, outputDir, frameCount) {
  await fs.promises.mkdir(outputDir, { recursive: true });
  
  const interval = (await getVideoDuration(videoPath)) / frameCount;
  const timestamps = Array.from({length: frameCount}, (_, i) => i * interval + 0.01);
  // 确保第一个时间戳不为0，避免总是取第一帧
  if (timestamps[0] === 0 && timestamps.length > 1) {
    timestamps[0] = interval;
  }
  return new Promise((resolve, reject) => {
    ffmpeg(videoPath)
      .on('end', resolve)
      .on('error', (err) => {
        console.error('提取关键帧时出错:', err);
        reject(err);
      })
      .screenshots({
        timestamps: timestamps,
        filename: 'frame_%03d.jpg',
        folder: outputDir,
        size: '1280x720',
        quality: 85
      });
  });
}

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  if (!fs.existsSync(UPLOAD_DIR)) {
    fs.mkdirSync(UPLOAD_DIR, { recursive: true });
  }
  console.log(`Server running on port ${PORT}`);
});